<?php
/**
 * @author  web_dxj@163.com
 * @time    2015-09-30 10:02
 */


/**
 * Menu_model
 */

//菜单格式1
//$arr = array(
//    array(
//        'id'     => 1,
//        'name'   => 'php',
//        'url'    => 'Url' ,
//        'target' => 'workspace',
//        'icon'   => '',
//        'path'   => '1'
//    ),
//    array(
//        'id' => 3,
//        'name' => 'php1',
//        'url'    => 'Url' ,
//        'target' => 'workspace',
//        'icon'   => '',
//        'path' => '1-3'
//    ),
//    array(
//        'id' => 2,
//        'name' => 'mysql',
//        'url'    => 'Url' ,
//        'target' => 'workspace',
//        'icon'   => '',
//        'path' => '2'
//    ),
//    array(
//        'id' => 6,
//        'name' => 'mysql1',
//        'url'    => 'Url' ,
//        'target' => 'workspace',
//        'icon'   => '',
//        'path' => '2-6'
//    ),
//    array(
//        'id' => 7,
//        'name' => 'mysql2',
//        'url'    => 'Url' ,
//        'target' => 'workspace',
//        'icon'   => '',
//        'path' => '2-7'
//    ),
//    array(
//        'id' => 5,
//        'name' => 'php11',
//        'url'    => 'Url' ,
//        'target' => 'workspace',
//        'icon'   => '',
//        'path' => '1-3-5'
//    ),
//    array(
//        'id' => 4,
//        'name' => 'php2',
//        'url'    => 'Url' ,
//        'target' => 'workspace',
//        'icon'   => '',
//        'path' => '1-4'
//    ),
//);


class Menu_model extends CI_Model {

    private $menu_arr = null;
    private $init_status = 0; // 初始化状态

    public function __construct() {
        parent::__construct();
    }

    /**
     * 初始化菜单模型参数
     * @param $json
     * @return $this
     */
    public function initialize($json) {
        $this->menu_arr = json_decode($json,TRUE);
        if ( FALSE !== $this->menu_arr )
        {
            $this->init_status = 1;
        }
        return $this;
    }

    /**
     * 数组排序
     *
     * @param $key           排序字段
     * @param string $type   排序规则 asc升序，desc降序
     * @return $this         链式操作
     * @throws Exception     抛出异常
     */
    public function sort($key,$type = 'asc') {

        if (!$this->init_status)
        {
            throw new Exception("菜单数组未初始化");
        }

        if (!is_string($key))
        {
            throw new Exception("非法参数key:参数key的值必须为字符串");
        }

        $keyvalue = $new_arr = array();
        foreach ($this->menu_arr as $k => $v)
        {
            if (!is_array($v) || !array_key_exists($key,$v))
            {
                throw new Exception("数组格式不正确或者不存在相应的key");
            }
            $keyvalue[$k] = $v[$key];
        }

        switch (strtolower($type))
        {
            case 'asc':
                natsort($keyvalue);
                break;
            case 'desc':
                natsort($keyvalue);
                $keyvalue = array_reverse($keyvalue);
                break;
            default:
                throw new Exception("非法参数type ：参数type的值必须为 'asc' 或 'desc'");
        }

        // 指针定位到数组第一个元素
        reset($keyvalue);
        foreach ($keyvalue as $k => $v)
        {
            $new_arr[$k] = $this->menu_arr[$k];
        }

        $this->menu_arr = $new_arr;
        return $this;
    }


    /**
     * 处理菜单层次结构
     *
     * @param string $chart
     * @return $this
     * @throws Exception
     */
    public function handler($chart = '&minus;&minus;') {

        if (!$this->init_status)
        {
            throw new Exception("菜单数组未初始化");
        }

        foreach ($this->menu_arr as $k => $v)
        {
            $this->menu_arr[$k]['name'] = str_repeat($chart,count(explode('-',$v['path'])) - 1) . $v['name'];
        }

        return $this;
    }

    /**
     * 根据key和value查找相应菜单
     *
     * @param $key
     * @param $value
     * @param $return_type   'index' | 'array'
     * @return null
     * @throws Exception
     */
    public function find($key,$value,$return_type = 'array') {

        $this->sort('path');

        if ( !($key && $value) )
        {
            return NULL;
        }

        foreach ($this->menu_arr as $k => $v)
        {
            if ( $v[$key] === $value )
            {
                if ( 'array' === $return_type )
                {
                    return $v;
                }
                return $k;
            }
        }

        return NULL;
    }


    public function count() {
        return count($this->menu_arr);
    }

    public function maxid() {
        $this->sort('path');
        if ( 0 === $this->count() )
        {
            return 1;
        }
        return end($this->menu_arr)['id'];
    }

    public function get_menu() {
        if (!$this->init_status)
        {
            throw new Exception("菜单数组未初始化");
        }
        return $this->menu_arr;
    }

    public function insert_menu($menu) {
        $this->sort('path');

        array_push( $this->menu_arr , $menu );
        return TRUE;
    }


    public function update_menu($menu) {

        $key = $this->find('id',$menu['id'],'index');
        if (empty($key))
        {
            return FALSE;
        }

        // replace
        $this->menu_arr[$key] = $menu;
        return TRUE;
    }


    /**
     * 删除某个菜单
     *
     * @param $id
     * @return bool
     * @throws Exception
     */
    public function del_menu($id) {

        $count = 0;

        if (!$this->init_status)
        {
            throw new Exception("菜单数组未初始化");
        }

        foreach ($this->menu_arr as $k => $v)
        {
            // 删除该菜单
            if ( intval($id) === $v['id'] )
            {
                unset($this->menu_arr[$k]);
                $count ++ ;
                continue;
            }

            // 该菜单的下级菜单自动上移一级
            $start = strpos($v['path'] , strval($id));
            if ( FALSE !== $start )
            {
                $this->menu_arr[$k]['path'] = str_replace($id . '-','',$v['path']);
                $count ++ ;
                continue;
            }
        }

        return boolval($count);
    }

    /**
     * 获取菜单的层次结构
     *
     * @param   int   $parent  值为 0，获取所有最顶层菜单
     * @param   int   $level   必须指定parent，获取parent下面的指定层级菜单
     * @return array  $menus
     */
    public function get_menu_level($parent = 0 , $level = 1) {

        $menus = array();

        if ( 0 === intval($parent) )
        {
            foreach ($this->menu_arr as $k => $v)
            {
                if ( FALSE === strpos($v['path'],'-') )
                {
                    $v['id'] = hashids_encode($v['id']);
                    array_push($menus,$v);
                }
            }
        }
        else
        {
            foreach ($this->menu_arr as $k => $v)
            {
                $path_arr = explode('-',$v['path']);
                $length   = count($path_arr);

                // 如果路径数组倒数第二个元素与$parent相等，则他是$parent下一级菜单
                if ( $length >= 2 && (intval($parent) === intval($path_arr[$length - ($level + 1)])) )
                {
                    $v['id'] = hashids_encode($v['id']);
                    array_push($menus,$v);
                }
            }
        }

        return $menus;
    }

}